
import time
import pymysql
import traceback

#自定义Mysql类
class MysqlUtil:
    #初始化
    def __init__(self, host='', port=3306, user='', passwd='', db='', charset='utf8'):
        self.host    = host;
        self.user    = user;
        self.passwd  = passwd;
        self.db      = db;
        self.port    = port;
        self.charset = charset
        #---------内部使用---------
        self.conn    = None;
        #建立Mysql连接
        self._conn();
        #end

    #建立Mysql连接
    def _conn(self):
        try:
            #建立连接
            self.conn = pymysql.Connection(host=self.host, user=self.user, passwd=self.passwd, 
                                           db=self.db, port=self.port, charset=self.charset);
            return True;
        except pymysql.Error as e:
            print("Error %d: %s" % (e.args[0], e.args[1]));
            traceback.print_exc();
            print("Connect MYSQL Error!");
            return False;
        #end

    # 发现连接断开后，自动重连
    def _reConn(self, RetryTimeMax=28800):
        #重试次数
        _ReTryTimes = 0;

        #重试重新连接
        while _ReTryTimes <= RetryTimeMax:
            try:
                # cping 校验连接是否异常
                self.conn.ping();
                #连接正常
                break;
            #连接异常
            except pymysql.Error as e:
                print("Error %d: %s" % (e.args[0], e.args[1]));
                traceback.print_exc();
                # 重新连接,成功退出
                if self._conn() == True:
                    break;
                #重新连接失败，重试一次
                _ReTryTimes += 1;
                # 连接不成功,休眠3秒钟后再次重试
                time.sleep(3);
        #end while
        #end

    #执行查询语句
    #返回值：成功 返回数据列表；失败 返回None；
    def Excute(self, sql='', DictCursor=None):
        try:
            #检查连接
            self._reConn();

            #游标类型：
            #   Cursor	        普通的游标对象，默认创建的游标对象
            #   SSCursor	    不缓存游标，主要用于当操作需要返回大量数据的时候
            #   DictCursor	    以字典的形式返回操作结果（ItemName作为Key）
            #   SSDictCursor	不缓存游标，将结果以字典的形式进行返回
            #获得游标
            if DictCursor:
                self.cursor = self.conn.cursor(pymysql.cursors.DictCursor); #字典型游标
            else:
                self.cursor = self.conn.cursor(); #普通游标
            #执行SQL
            self.cursor.execute(sql);
            #获得返回结果
            result = self.cursor.fetchall();
            #关闭游标
            self.cursor.close();
            #返回结果
            return result;

        except pymysql.Error as e:
            print("Error %d: %s" % (e.args[0], e.args[1]));
            traceback.print_exc();
            return None;

    #执行事务类SQL，需要进行Commit和异常时Rollback
    #返回值：成功 返回结果列表；失败返回None;
    def ExcuteWithCommit(self, sql='', args=None):
        try:
            #校验连接
            self._reConn();
            #获取游标
            self.cursor = self.conn.cursor(pymysql.cursors.DictCursor);
            #设置字符集
            self.cursor.execute("set names utf8");
            #执行SQL
            result = self.cursor.execute(sql, args);
            #提交事务
            self.conn.commit();
            #关闭游标
            self.cursor.close();
            #成功，返回result;
            return result;
        
        except pymysql.Error as e:
            #事务回滚
            self.conn.rollback();
            #关闭游标
            self.cursor.close();
            print("Error %d: %s" % (e.args[0], e.args[1]));
            print("sql=", sql);
            traceback.print_exc();
            return None;
        #end

    #释放Mysql资源
    def Close(self):
        self.conn.close();
        #end

#测试数据库类
if __name__ == "__main__":
    #建立mysql连接 host='', port=3306, user='', passwd='', db='', charset='utf8'
    MysqlH = MysqlUtil(host='120.79.71.7', user='root', passwd='H6Kp7M5YF6Gcybht',db='foreclosure');
    #执行SQL语句（无需Commit）
    result = MysqlH.Excute('show tables');
    print(result)
    #
    MysqlH.Close();

